/*
 * $Id: PerforceStatus.java 23 2002-09-29 13:59:30Z bpruessmann $
 * 
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 *    David Corbin  - added several status: BRANCHED_TO, REOPENED_FOR_ADD, OPENED_FOR_DELETE
 */
package net.sourceforge.p4eclipse.core.api;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.TreeMap;

import net.sourceforge.p4eclipse.ui.PerforceUIPlugin;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

/**
  * @version 	$Revision: 23 $
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  * @author		<a href="mailto:dcorbin@users.sourceforge.net">David Corbin</a>
  */
public class PerforceStatus
{
	// IStatus.OK
	public static final IStatus OK                        = new Status(IStatus.OK, PerforceUIPlugin.ID, 1000, "", null); //$NON-NLS-1$
	public static final IStatus FILES_UPTODATE            = new Status(IStatus.OK, PerforceUIPlugin.ID, 1001, "FILE(S) UP-TO-DATE", null); //$NON-NLS-1$
	public static final IStatus OPENED_FOR_EDIT           = new Status(IStatus.OK, PerforceUIPlugin.ID, 1002, "OPENED FOR EDIT", null); //$NON-NLS-1$
	public static final IStatus WAS_EDIT_REVERTED         = new Status(IStatus.OK, PerforceUIPlugin.ID, 1003, "WAS EDIT REVERTED", null); //$NON-NLS-1$
	public static final IStatus WAS_ADD_ABANDONED         = new Status(IStatus.OK, PerforceUIPlugin.ID, 1004, "WAS ADD ABANDONED", null); //$NON-NLS-1$
	public static final IStatus OPENED_FOR_ADD            = new Status(IStatus.OK, PerforceUIPlugin.ID, 1005, "OPENED FOR ADD", null); //$NON-NLS-1$
	public static final IStatus CURRENTLY_OPENED_FOR_ADD  = new Status(IStatus.OK, PerforceUIPlugin.ID, 1006, "CURRENTLY OPENED FOR ADD", null); //$NON-NLS-1$
	public static final IStatus CURRENTLY_OPENED_FOR_EDIT = new Status(IStatus.OK, PerforceUIPlugin.ID, 1007, "CURRENTLY OPENED FOR EDIT", null); //$NON-NLS-1$
	public static final IStatus UPDATING                  = new Status(IStatus.OK, PerforceUIPlugin.ID, 1008, "UPDATING", null); //$NON-NLS-1$
	public static final IStatus REOPENED_CHANGE           = new Status(IStatus.OK, PerforceUIPlugin.ID, 1009, "REOPENED CHANGE", null); //$NON-NLS-1$
	public static final IStatus NOTHING_CHANGED           = new Status(IStatus.OK, PerforceUIPlugin.ID, 1010, "NOTHING CHANGED", null); //$NON-NLS-1$
	public static final IStatus REFRESHING                = new Status(IStatus.OK, PerforceUIPlugin.ID, 1011, "REFRESHING", null); //$NON-NLS-1$
	public static final IStatus ADDED_AS                  = new Status(IStatus.OK, PerforceUIPlugin.ID, 1012, "ADDED AS", null); //$NON-NLS-1$
	public static final IStatus DELETED_AS                = new Status(IStatus.OK, PerforceUIPlugin.ID, 1013, "DELETED AS", null); //$NON-NLS-1$
	public static final IStatus BRANCHED_TO			    = new Status(IStatus.OK, PerforceUIPlugin.ID, 1014, "BRANCH/SYNC",null); //$NON-NLS-1$
	public static final IStatus REOPENED_FOR_ADD          = new Status(IStatus.OK, PerforceUIPlugin.ID, 1015, "REOPENED FOR ADD", null); //$NON-NLS-1$
	public static final IStatus OPENED_FOR_DELETE         = new Status(IStatus.OK, PerforceUIPlugin.ID, 1016, "OPENED FOR DELETE", null); //$NON-NLS-1$
	public static final IStatus WAS_DELETE_REVERTED       = new Status(IStatus.OK, PerforceUIPlugin.ID, 1017, "WAS DELETE REVERTED", null); //$NON-NLS-1$
	public static final IStatus NO_FILES_TO_RESOLVE       = new Status(IStatus.OK, PerforceUIPlugin.ID, 1018, "NO FILE(S) TO RESOLVE", null); //$NON-NLS-1$
		
	// IStatus.INFO
	public static final IStatus INFO                = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2000, "", null); //$NON-NLS-1$
	public static final IStatus EMPTY_ASSUMING_TEXT = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2001, "EMPTY ASSUMING TEXT", null); //$NON-NLS-1$
	public static final IStatus ALSO_OPENED_BY      = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2002, "ALSO OPENED BY", null); //$NON-NLS-1$
	public static final IStatus MUST_SYNC_RESOLVE_BEFORE_SUBMITTING = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2003, "MUST SYNC/RESOLVE BEFORE SUBMITTING", null); //$NON-NLS-1$
	public static final IStatus LOCKED_BY           = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2004, "LOCKED BY", null); //$NON-NLS-1$
	public static final IStatus IS_OPENED_AND_NOT_BEING_CHANGED = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2005, "IS OPENED AND NOT BEING CHANGED", null); //$NON-NLS-1$
	public static final IStatus NO_SUCH_FILES       = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2006, "NO SUCH FILE(S)", null); //$NON-NLS-1$
	public static final IStatus NO_FILES_RESOLVED   = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2007, "NO FILE(S) RESOLVED", null); //$NON-NLS-1$ 
	public static final IStatus FILES_NOT_ON_CLIENT = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2008, "FILE(S) NOT ON CLIENT", null); //$NON-NLS-1$
	public static final IStatus FILES_NOT_OPENED_FOR_EDIT = new Status(IStatus.INFO, PerforceUIPlugin.ID, 2009, "FILE(S) NOT OPENED FOR EDIT", null); //$NON-NLS-1$
		
	// IStatus.ERROR
	public static final IStatus ERROR                          = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 4000, "", null); //$NON-NLS-1$
	public static final IStatus MUST_RESOLVE_BEFORE_SUBMITTING = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 4001, "MUST RESOLVE BEFORE SUBMITTING", null); //$NON-NLS-1$
	public static final IStatus MUST_RESOLVE                   = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 4002, "MUST RESOLVE", null); //$NON-NLS-1$
	public static final IStatus CANT_ADD_EXCLUSIVE_FILE_ALREADY_OPENED = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 4003, "CAN'T ADD EXCLUSIVE FILE ALREADY OPENED", null); //$NON-NLS-1$
	public static final IStatus ALREADY_LOCKED_BY              = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 4004, "ALREADY LOCKED BY", null); //$NON-NLS-1$
	public static final IStatus MUST_REFER_TO_CLIENT           = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 4005, "MUST REFER TO CLIENT", null); //$NON-NLS-1$
	
	private static final String[] KNOWN_TOKENS = { "FILE(S)",    //$NON-NLS-1$
	                                               "UP-TO-DATE", //$NON-NLS-1$
		                                           "WAS",        //$NON-NLS-1$
		                                           "EDIT",       //$NON-NLS-1$
		                                           "REVERTED",   //$NON-NLS-1$
		                                           "OPENED",     //$NON-NLS-1$
		                                           "FOR",        //$NON-NLS-1$
		                                           "ADD",        //$NON-NLS-1$
		                                           "ABANDONED",  //$NON-NLS-1$
		                                           "EMPTY",      //$NON-NLS-1$
		                                           "ASSUMING",   //$NON-NLS-1$
		                                           "TEXT",       //$NON-NLS-1$
		                                           "CURRENTLY",  //$NON-NLS-1$
		                                           "ALSO",       //$NON-NLS-1$
		                                           "BY",         //$NON-NLS-1$
		                                           "MUST",       //$NON-NLS-1$
		                                           "RESOLVE",    //$NON-NLS-1$
		                                           "BEFORE",     //$NON-NLS-1$
		                                           "SUBMITTING", //$NON-NLS-1$
		                                           "SYNC/RESOLVE",//$NON-NLS-1$
		                                           "BRANCH/SYNC",//$NON-NLS-1$
		                                           "CAN'T",      //$NON-NLS-1$
		                                           "EXCLUSIVE",  //$NON-NLS-1$
		                                           "FILE",       //$NON-NLS-1$
		                                           "ALREADY",    //$NON-NLS-1$
		                                           "LOCKED",     //$NON-NLS-1$
		                                           "UPDATING",   //$NON-NLS-1$
		                                           "REOPENED",   //$NON-NLS-1$
		                                           "CHANGE",     //$NON-NLS-1$
		                                           "NOTHING",    //$NON-NLS-1$
		                                           "CHANGED",    //$NON-NLS-1$
		                                           "REFER",      //$NON-NLS-1$
		                                           "TO",         //$NON-NLS-1$
		                                           "CLIENT",     //$NON-NLS-1$
		                                           "ADDED",      //$NON-NLS-1$
		                                           "AS",         //$NON-NLS-1$
		                                           "IS",         //$NON-NLS-1$
		                                           "AND",        //$NON-NLS-1$
		                                           "NOT",        //$NON-NLS-1$
		                                           "BEING",      //$NON-NLS-1$
		                                           "DELETED",    //$NON-NLS-1$
		                                           "DELETE",    //$NON-NLS-1$
		                                           "NO",         //$NON-NLS-1$
		                                           "SUCH",       //$NON-NLS-1$
		                                           "REFRESHING", //$NON-NLS-1$
		                                           "RESOLVED",   //$NON-NLS-1$
		                                           "ON" };   //$NON-NLS-1$
	
	private static List KNOWN_TOKENS_LIST;
	private static Map  STATUS_MAP;

	private static final PerforceStatus dummy = new PerforceStatus();
	
	{
		KNOWN_TOKENS_LIST = Arrays.asList(KNOWN_TOKENS);
		Collections.sort(KNOWN_TOKENS_LIST);
		
		STATUS_MAP = new TreeMap();
		
		// IStatus.OK
		STATUS_MAP.put(FILES_UPTODATE.getMessage(), FILES_UPTODATE);
		STATUS_MAP.put(OPENED_FOR_EDIT.getMessage(), OPENED_FOR_EDIT);
		STATUS_MAP.put(WAS_EDIT_REVERTED.getMessage(), WAS_EDIT_REVERTED);
		STATUS_MAP.put(WAS_ADD_ABANDONED.getMessage(), WAS_ADD_ABANDONED);
		STATUS_MAP.put(OPENED_FOR_ADD.getMessage(), OPENED_FOR_ADD);
		STATUS_MAP.put(CURRENTLY_OPENED_FOR_ADD.getMessage(), CURRENTLY_OPENED_FOR_ADD);
		STATUS_MAP.put(CURRENTLY_OPENED_FOR_EDIT.getMessage(), CURRENTLY_OPENED_FOR_EDIT);
		STATUS_MAP.put(UPDATING.getMessage(), UPDATING);
		STATUS_MAP.put(REOPENED_CHANGE.getMessage(), REOPENED_CHANGE);
		STATUS_MAP.put(NOTHING_CHANGED.getMessage(), NOTHING_CHANGED);
		STATUS_MAP.put(REFRESHING.getMessage(), REFRESHING);
		STATUS_MAP.put(ADDED_AS.getMessage(), ADDED_AS);
		STATUS_MAP.put(DELETED_AS.getMessage(), DELETED_AS);
		STATUS_MAP.put(BRANCHED_TO.getMessage(), BRANCHED_TO);
		STATUS_MAP.put(REOPENED_FOR_ADD.getMessage(), REOPENED_FOR_ADD);
		STATUS_MAP.put(OPENED_FOR_DELETE.getMessage(), OPENED_FOR_DELETE);
		STATUS_MAP.put(WAS_DELETE_REVERTED.getMessage(), WAS_DELETE_REVERTED);
		STATUS_MAP.put(NO_FILES_TO_RESOLVE.getMessage(), NO_FILES_TO_RESOLVE);
				
		// IStatus.INFO
		STATUS_MAP.put(EMPTY_ASSUMING_TEXT.getMessage(), EMPTY_ASSUMING_TEXT);
		STATUS_MAP.put(ALSO_OPENED_BY.getMessage(), ALSO_OPENED_BY);
		STATUS_MAP.put(MUST_SYNC_RESOLVE_BEFORE_SUBMITTING.getMessage(), MUST_SYNC_RESOLVE_BEFORE_SUBMITTING);
		STATUS_MAP.put(LOCKED_BY.getMessage(), LOCKED_BY);
		STATUS_MAP.put(IS_OPENED_AND_NOT_BEING_CHANGED.getMessage(), IS_OPENED_AND_NOT_BEING_CHANGED);
		STATUS_MAP.put(NO_SUCH_FILES.getMessage(), NO_SUCH_FILES);
		STATUS_MAP.put(NO_FILES_RESOLVED.getMessage(), NO_FILES_RESOLVED);
		STATUS_MAP.put(FILES_NOT_ON_CLIENT.getMessage(), FILES_NOT_ON_CLIENT);
		STATUS_MAP.put(FILES_NOT_OPENED_FOR_EDIT.getMessage(), FILES_NOT_OPENED_FOR_EDIT);
		
		// IStatus.ERROR
		STATUS_MAP.put(MUST_RESOLVE_BEFORE_SUBMITTING .getMessage(), MUST_RESOLVE_BEFORE_SUBMITTING);
		STATUS_MAP.put(MUST_RESOLVE.getMessage(), MUST_RESOLVE);
		STATUS_MAP.put(CANT_ADD_EXCLUSIVE_FILE_ALREADY_OPENED.getMessage(), CANT_ADD_EXCLUSIVE_FILE_ALREADY_OPENED);
		STATUS_MAP.put(ALREADY_LOCKED_BY.getMessage(), ALREADY_LOCKED_BY);
		STATUS_MAP.put(MUST_REFER_TO_CLIENT.getMessage(), MUST_REFER_TO_CLIENT);
	}

	private IStatus status;	
	private String originalMessage;
		
	public static IStatus decode(String perforceString, int severity)
	{
		int pos = perforceString.lastIndexOf(" - "); //$NON-NLS-1$
		if (pos == -1)
			return new Status(severity, OK.getPlugin(), severity, perforceString.trim(), OK.getException());
	
		StringBuffer buffer = new StringBuffer();
		StringTokenizer tokenizer = new StringTokenizer(perforceString.substring(pos + 3).toUpperCase(), " .,;\n"); //$NON-NLS-1$
		while (tokenizer.hasMoreTokens())
		{
			String token = tokenizer.nextToken();			
			int index = Collections.binarySearch(KNOWN_TOKENS_LIST, token);

			if (index >= 0)
				buffer.append(token);

			if (buffer.length() > 0 && buffer.charAt(buffer.length() - 1) != ' ')
				buffer.append(' ');	//$NON-NLS-1$
		}

		IStatus result = null;
		
		String key = buffer.toString().trim();
		IStatus status = (IStatus)STATUS_MAP.get(key);
		if (status == null)
			result = new Status(IStatus.ERROR, PerforceUIPlugin.ID, 999, "Unknown result: " + perforceString + "<" + key + ">", null); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		else
			result = new Status(status.getSeverity(), status.getPlugin(), status.getCode(), perforceString.trim(), status.getException());		
			
		return result;
	}			
}
